<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue';
import { useStitchingStore } from '../../stores/stitchingStore';
import { formatFileSize } from '../../utils/fileUtils';
import imageStitchingService from '../../services/ImageStitchingService';
import Viewer from 'viewerjs';
import 'viewerjs/dist/viewer.css';

const stitchingStore = useStitchingStore();
const format = ref('png');
const quality = ref(0.9);
const showMetadata = ref(false);

// Viewer.js instance
const viewer = ref<Viewer | null>(null);
const imageRef = ref<HTMLImageElement | null>(null);
const imageContainer = ref<HTMLElement | null>(null);

// Compute estimated file size based on dimensions and format
const estimatedFileSize = computed(() => {
  if (!stitchingStore.stitchedImage) return 0;

  const { width, height } = stitchingStore.stitchedImage;
  const pixelCount = width * height;

  // More accurate estimation based on format and quality:
  let bytesPerPixel;

  if (format.value === 'png') {
    // PNG: Typically between 0.5 and 2 bytes per pixel depending on content
    // Use a more conservative estimate that accounts for better compression
    bytesPerPixel = 0.8;
  } else {
    // JPEG: Non-linear relationship between quality and file size
    // High quality settings (90-100) increase file size dramatically
    if (quality.value > 0.9) {
      bytesPerPixel = 0.25 * quality.value * 3; // Much larger at highest quality
    } else if (quality.value > 0.8) {
      bytesPerPixel = 0.25 * quality.value * 2; // Larger at high quality
    } else {
      bytesPerPixel = 0.25 * quality.value; // Linear at lower qualities
    }
  }

  return pixelCount * bytesPerPixel;
});

// Initialize and control Viewer.js
function initViewer() {
  if (!imageRef.value) return;

  // Destroy existing viewer if it exists
  if (viewer.value) {
    viewer.value.destroy();
  }

  // Calculate initial zoom ratio to fit the image properly in the container
  const calculateInitialZoom = () => {
    if (!stitchingStore.stitchedImage || !imageContainer.value) return 0.5;

    const containerWidth = imageContainer.value.clientWidth;
    const containerHeight = imageContainer.value.clientHeight;
    const imageWidth = stitchingStore.stitchedImage.width;
    const imageHeight = stitchingStore.stitchedImage.height;

    // Calculate the ratio that would fit the image in the container
    const widthRatio = containerWidth / imageWidth;
    const heightRatio = containerHeight / imageHeight;

    // Use the smaller ratio to ensure the image fits completely
    return Math.min(widthRatio, heightRatio, 1);
  };

  const initialZoom = calculateInitialZoom();

  // Initialize Viewer.js with improved options
  viewer.value = new Viewer(imageRef.value, {
    inline: true,
    navbar: false,
    title: false,
    toolbar: {
      zoomIn: true,
      zoomOut: true,
      oneToOne: true,
      reset: true,
      prev: false,
      next: false,
      rotateLeft: true,
      rotateRight: true,
      flipHorizontal: true,
      flipVertical: true,
      fullscreen: true,
    },
    viewed() {
      // This event fires when the image is viewed (loaded)
      console.log('Image viewed');

      // Set initial zoom to fit the container properly
      if (viewer.value) {
        viewer.value.zoomTo(initialZoom);
      }
    },
    ready() {
      // This event fires when the viewer is ready
      console.log('Viewer is ready');
    },
    // Optimize for large images
    minZoomRatio: 0.03,
    maxZoomRatio: 10,
    zoomRatio: 0.1, // Smaller zoom steps for more precise control
    transition: false, // Disable transition for better performance with large images
    zoomable: true,
    scalable: true,
    toggleOnDblclick: true,
  });
}

function toggleMetadata() {
  showMetadata.value = !showMetadata.value;
}

const isDownloading = ref(false);
const downloadProgress = ref(0);

async function downloadImage() {
  if (!stitchingStore.stitchedImage) {
    console.error('No stitched image available');
    return;
  }

  // Generate filename based on current date and time
  const now = new Date();
  const timestamp = now.toISOString().replace(/[:.]/g, '-');
  const extension = format.value === 'jpg' ? 'jpg' : 'png';
  const filename = `stitched-image-${timestamp}.${extension}`;

  // Set downloading state
  isDownloading.value = true;
  downloadProgress.value = 0;

  try {
    // Download image with progress tracking
    await imageStitchingService.downloadStitchedImage(
      stitchingStore.stitchedImage,
      format.value,
      quality.value,
      filename,
      (progress) => {
        downloadProgress.value = progress;
      }
    );
  } catch (error) {
    console.error('下载图片失败:', error);
    alert('下载图片失败，请重试');
  } finally {
    // Reset downloading state
    isDownloading.value = false;
    downloadProgress.value = 0;
  }
}

function downloadMetadata() {
  if (!stitchingStore.metadata) {
    console.error('No metadata available');
    return;
  }

  // Generate filename based on current date and time
  const now = new Date();
  const timestamp = now.toISOString().replace(/[:.]/g, '-');
  const filename = `metadata-${timestamp}.json`;

  // Set downloading state
  isDownloading.value = true;
  downloadProgress.value = 0;

  try {
    // Download metadata (this is a synchronous operation)
    imageStitchingService.downloadMetadata(stitchingStore.metadata, filename);
    downloadProgress.value = 100;

    // Add a small delay to show the loading indicator
    setTimeout(() => {
      isDownloading.value = false;
      downloadProgress.value = 0;
    }, 500);
  } catch (error) {
    console.error('下载元数据失败:', error);
    alert('下载元数据失败，请重试');
    isDownloading.value = false;
    downloadProgress.value = 0;
  }
}

async function downloadBoth() {
  if (!stitchingStore.stitchedImage || !stitchingStore.metadata) {
    console.error('No stitched image or metadata available');
    return;
  }

  // Generate filename based on current date and time
  const now = new Date();
  const timestamp = now.toISOString().replace(/[:.]/g, '-');
  const extension = format.value === 'jpg' ? 'jpg' : 'png';
  const filename = `stitched-image-with-metadata-${timestamp}.${extension}`;

  // Set downloading state
  isDownloading.value = true;
  downloadProgress.value = 0;

  try {
    // Download image with embedded metadata with progress tracking
    await imageStitchingService.downloadStitchedImageWithMetadata(
      stitchingStore.stitchedImage,
      stitchingStore.metadata,
      format.value,
      quality.value,
      filename,
      (progress) => {
        // Update progress for the first 80% of the process
        downloadProgress.value = Math.round(progress * 0.8);
      }
    );

    // Update progress to 90%
    downloadProgress.value = 90;

    // Also download metadata as a separate file
    const metadataFilename = `metadata-${timestamp}.json`;
    imageStitchingService.downloadMetadata(stitchingStore.metadata, metadataFilename);

    // Complete the progress
    downloadProgress.value = 100;

    // Add a small delay before hiding the progress indicator
    setTimeout(() => {
      isDownloading.value = false;
      downloadProgress.value = 0;
    }, 500);
  } catch (error) {
    console.error('下载图片和元数据失败:', error);
    alert('下载图片和元数据失败，请重试');
    isDownloading.value = false;
    downloadProgress.value = 0;
  }
}

// Watch for changes in the stitched image and reinitialize the viewer
import { watch } from 'vue';

// Initialize viewer when component is mounted
onMounted(() => {
  // Wait for the DOM to be updated
  nextTick(() => {
    if (stitchingStore.stitchedImage) {
      initViewer();
    }
  });
});

// Watch for changes in the stitched image
watch(() => stitchingStore.stitchedImage, (newImage, oldImage) => {
  if (newImage) {
    // Force viewer destruction before DOM update
    if (viewer.value) {
      viewer.value.destroy();
      viewer.value = null;
    }

    // Wait for the DOM to be updated with the new image
    nextTick(() => {
      // Reinitialize the viewer with the new image
      initViewer();
    });
  }
}, { deep: true });

// Clean up viewer when component is unmounted
onUnmounted(() => {
  if (viewer.value) {
    viewer.value.destroy();
  }
});
</script>

<template>
  <div v-if="stitchingStore.stitchedImage" class="stitched-image-viewer">
    <h3>拼接结果</h3>

    <div class="image-controls">
      <button @click="toggleMetadata" class="metadata-toggle">
        {{ showMetadata ? '隐藏元数据' : '显示元数据' }}
      </button>
    </div>

    <div ref="imageContainer" class="image-container">
      <img ref="imageRef" :src="stitchingStore.stitchedImage.url" alt="拼接图片" class="viewer-image">
    </div>

    <div class="image-info">
      <p>尺寸: {{ stitchingStore.stitchedImage.width }}x{{ stitchingStore.stitchedImage.height }} 像素</p>
      <p>预计文件大小: {{ formatFileSize(estimatedFileSize) }}</p>
    </div>

    <div v-if="showMetadata && stitchingStore.metadata" class="metadata-preview">
      <h4>元数据预览</h4>
      <div class="metadata-content">
        <pre>{{ JSON.stringify(stitchingStore.metadata, null, 2) }}</pre>
      </div>
    </div>

    <div class="download-options">
      <div class="control-group">
        <label for="format">导出格式</label>
        <select id="format" v-model="format">
          <option value="png">PNG</option>
          <option value="jpg">JPEG</option>
        </select>
      </div>

      <div v-if="format === 'jpg'" class="control-group">
        <label for="quality">质量 ({{ Math.round(quality * 100) }}%)</label>
        <input id="quality" type="range" min="0.1" max="1" step="0.1" v-model.number="quality">
      </div>

      <div v-if="isDownloading" class="download-progress">
        <div class="loading-spinner">
          <div class="spinner"></div>
        </div>
        <p>下载中...</p>
      </div>

      <div class="button-group">
        <button @click="downloadImage" class="download-button" :disabled="isDownloading">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
            <path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
          </svg>
          下载图片
        </button>
        <button @click="downloadMetadata" class="download-button" :disabled="isDownloading">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
            <path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
          </svg>
          下载元数据
        </button>
        <button @click="downloadBoth" class="download-button" :disabled="isDownloading">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
            <path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
          </svg>
          下载图片和元数据
        </button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.stitched-image-viewer {
  margin-top: 2rem;
}

h3 {
  margin-bottom: 1rem;
}

.image-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}

.zoom-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.zoom-controls button {
  width: 32px;
  height: 32px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.metadata-toggle {
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
}

.image-container {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
  background-color: #f5f5f5;
  height: 500px;
  position: relative;
}

/* Viewer.js specific styles */
.viewer-container {
  background-color: rgba(0, 0, 0, 0.8);
}

.viewer-canvas {
  background-color: transparent;
}

.viewer-footer {
  background-color: rgba(0, 0, 0, 0.5);
}

.viewer-toolbar {
  background-color: rgba(0, 0, 0, 0.5);
}

.viewer-button {
  color: #fff;
  cursor: pointer;
}

.viewer-button:hover {
  color: #4caf50;
}

/* Hide the image initially, Viewer.js will handle display */
.viewer-image {
  max-width: 100%;
  max-height: 500px;
  display: block;
  margin: 0 auto;
}

.image-info {
  margin-top: 0.5rem;
  font-size: 0.9rem;
  color: #666;
}

.download-options {
  margin-top: 1.5rem;
  padding: 1.5rem;
  background-color: #f5f5f5;
  border-radius: 8px;
}

.control-group {
  margin-bottom: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

label {
  font-weight: 500;
}

select {
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 1rem;
}

.button-group {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

@media (max-width: 576px) {
  .button-group {
    flex-direction: column;
  }

  .image-controls {
    flex-direction: column;
    gap: 0.5rem;
    align-items: flex-start;
  }

  .image-container {
    height: 300px;
  }
}

button {
  padding: 0.75rem 1rem;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 1rem;
}

button:hover {
  background-color: #45a049;
}

.metadata-preview {
  margin-top: 1.5rem;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
}

.metadata-preview h4 {
  margin: 0;
  padding: 1rem;
  background-color: #f5f5f5;
  border-bottom: 1px solid #e0e0e0;
}

.metadata-content {
  max-height: 300px;
  overflow: auto;
  padding: 1rem;
  background-color: #fafafa;
}

.metadata-content pre {
  margin: 0;
  white-space: pre-wrap;
  font-family: monospace;
  font-size: 0.9rem;
}

.download-button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.download-progress {
  margin-bottom: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.loading-spinner {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 0.5rem;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(76, 175, 80, 0.3);
  border-radius: 50%;
  border-top-color: #4caf50;
  animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}
</style>